package com.dc.cameraxtest

import android.Manifest
import android.content.ContentValues
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Rect
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.ImageProxy
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.dc.cameraxtest.databinding.ActivityOcrBinding
import com.dc.cameraxtest.utils.ImageProcessing
import com.dc.cameraxtest.utils.RecognizeTextUtils
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class OcrActivity : AppCompatActivity() {
    private lateinit var viewBinding: ActivityOcrBinding
    private lateinit var cameraExecutor:ExecutorService

    private var imageCapture: ImageCapture? = null
    companion object {
        private const val TAG = "OcrActivity"
        private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
        private const val REQUEST_CODE_PERMISSIONS = 10
        private val REQUIRED_PERMISSIONS =
            mutableListOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO).apply { }.toTypedArray()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewBinding = ActivityOcrBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        initView()
    }

    private fun initView() {

        // Request camera permissions
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(this,
                REQUIRED_PERMISSIONS,
                REQUEST_CODE_PERMISSIONS
            )
        }
        viewBinding.btnCapture.setOnClickListener { takePhoto() }
        viewBinding.btnReject.setOnClickListener { showAcceptedRejectedButton(false) }
        viewBinding.btnAccept.setOnClickListener { savePhoto() }
        cameraExecutor = Executors.newSingleThreadExecutor()
    }

    private fun savePhoto() {
        // 存图路径和参数（时间、文件类型）
        val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis())
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, name)
            put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
        }
        // 我们希望将输出保存在 MediaStore 中，以便其他应用可以显示它
        val outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver,
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).build()

        // 拍照后的回调函数
        imageCapture?.takePicture(outputOptions, ContextCompat.getMainExecutor(this),
            object : ImageCapture.OnImageSavedCallback {
                override fun onError(exc: ImageCaptureException) {
                    Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
                }

                override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                    val msg = "Photo capture succeeded: ${outputFileResults.savedUri}"
                    Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
                    Log.d(TAG, msg)
                }
            }
        )
    }


    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
            val preview = Preview.Builder().build().also {
                it.setSurfaceProvider(viewBinding.viewFinder.surfaceProvider)
            }
            imageCapture = ImageCapture.Builder().build()
            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
            try {
                cameraProvider.unbindAll()
                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
            } catch (e: Exception) {
                e.printStackTrace()
                // 有多种原因可能会导致此代码失败，例如应用不再获得焦点。在此记录日志。
                Log.e(TAG, "Use case binding failed", e)
            }
        }, ContextCompat.getMainExecutor(this))
    }

    private fun takePhoto() {
        imageCapture?.takePicture(ContextCompat.getMainExecutor(this),
            object : ImageCapture.OnImageCapturedCallback() {
                override fun onCaptureSuccess(image: ImageProxy) {
                    super.onCaptureSuccess(image)
                    // 获取框的位置和大小
                    val frameRect: Rect = getFrameRect()
                    val bitmap: Bitmap? = viewBinding.viewFinder.bitmap // 从textureview中把gitmap取出来

                    // 裁剪图像，只获取框内部分
                    if (bitmap != null) {
                        // 裁剪图像，只获取框内部分
                        val croppedBitmap = Bitmap.createBitmap(
                            bitmap,
                            frameRect.left,
                            frameRect.top,
                            frameRect.width(),
                            frameRect.height()
                        )
                        showAcceptedRejectedButton(true) // 这里主要做按键切换，点了拍照按键后，拍照按键隐藏，显示接受和拒绝按键
                        viewBinding.ivBitmap.setImageBitmap(croppedBitmap) // 不太清楚为什么要这样做

                        val result: Boolean = ImageProcessing.checkIfImageIsBlurred(croppedBitmap)
                        if (!result) {
                            Toast.makeText( applicationContext, "图像过于模糊,请重拍", Toast.LENGTH_SHORT ).show()
                        } else {

                            RecognizeTextUtils.recognizeTextFromBitmap(croppedBitmap) { result ->
                                // 在这里处理识别结果
                                Log.e(TAG, "onCaptureSuccess: result = $result")
                                viewBinding.tvOcrText.text = result
                            }
                        }
                    }
                }

                override fun onError(exception: ImageCaptureException) {
                    super.onError(exception)
                    Log.e(TAG, "onError: ${exception.message}")
                }
            }
        )
    }

    private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                startCamera()
            } else {
                Toast.makeText(this, "Permissions not granted by the user", Toast.LENGTH_SHORT).show()
                finish()
            }
        }
    }

    private fun getFrameRect(): Rect {
        // 获取框的左上角和右下角坐标，框的大小
        val frame = viewBinding.frameOverlay
        val left = frame.left
        val top = frame.top
        val right = frame.right
        val bottom = frame.bottom
        Log.e(TAG,"getFrameRect: left=$left, top=$top, right=$right, bottom=$bottom")
        return Rect(left, top, right, bottom)
    }


    // 捕获按键和接受拒绝按键的切换
    private fun showAcceptedRejectedButton(acceptedRejected: Boolean) {
        if (acceptedRejected) {
//            CameraX.u (preview, imageAnalysis)
            viewBinding.clResult.visibility = View.VISIBLE
            viewBinding.btnCapture.hide()
            viewBinding.viewFinder.visibility = View.GONE
            viewBinding.frameOverlay.visibility = View.GONE
        } else {
            viewBinding.btnCapture.show()
            viewBinding.clResult.visibility = View.GONE
            viewBinding.viewFinder.visibility = View.VISIBLE
            viewBinding.viewFinder.post(Runnable { startCamera() })
            viewBinding.frameOverlay.visibility = View.VISIBLE
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        cameraExecutor.shutdown()
    }
}